<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.0">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">



<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.4/css/all.min.css" integrity="sha256-mUZM63G8m73Mcidfrv5E+Y61y7a12O5mW4ezU3bxqW4=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/animate.css@3.1.1/animate.min.css" integrity="sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE=" crossorigin="anonymous">

<script class="next-config" data-name="main" type="application/json">{"hostname":"tallgy.gitee.io","root":"/","images":"/images","scheme":"Muse","darkmode":false,"version":"8.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":false,"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"}}</script><script src="/js/config.js"></script>
<meta name="description" content="JavaScript原型链123456原型链，就像是Java中的继承一样，可以让子类取访问父类的属性，可以将一些公用的东西写在原型上。是一个 __proto__ 的不断指向上一层。同时箭头函数没有 prototype ，所以不能使用new方法  先看一张图，简单来说 ​        原型其实就是一个方法的实例，然后每一个方法的实例有一个__proto__ 的指向。这个指向会直到指到null为止。">
<meta property="og:type" content="article">
<meta property="og:title" content="JavaScript原型链">
<meta property="og:url" content="http://tallgy.gitee.io/2021/11/09/JavaScript/%E5%AF%B9%E8%B1%A1/JavaScript%E5%8E%9F%E5%9E%8B%E9%93%BE/index.html">
<meta property="og:site_name" content="tallgy&#39;s blog">
<meta property="og:description" content="JavaScript原型链123456原型链，就像是Java中的继承一样，可以让子类取访问父类的属性，可以将一些公用的东西写在原型上。是一个 __proto__ 的不断指向上一层。同时箭头函数没有 prototype ，所以不能使用new方法  先看一张图，简单来说 ​        原型其实就是一个方法的实例，然后每一个方法的实例有一个__proto__ 的指向。这个指向会直到指到null为止。">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="http://tallgy.gitee.io/.io//290701352241158.jpg">
<meta property="og:image" content="http://tallgy.gitee.io/.io//image-20211110100356010.png">
<meta property="og:image" content="http://tallgy.gitee.io/.io//image-20211110101346723.png">
<meta property="article:published_time" content="2021-11-09T12:57:32.000Z">
<meta property="article:modified_time" content="2023-06-25T08:57:29.338Z">
<meta property="article:author" content="tallgy">
<meta property="article:tag" content="随笔">
<meta property="article:tag" content="JavaScript">
<meta property="article:tag" content="原型链">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="http://tallgy.gitee.io/.io//290701352241158.jpg">


<link rel="canonical" href="http://tallgy.gitee.io/2021/11/09/JavaScript/%E5%AF%B9%E8%B1%A1/JavaScript%E5%8E%9F%E5%9E%8B%E9%93%BE/">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":false,"isPost":true,"lang":"zh-CN","comments":true,"permalink":"http://tallgy.gitee.io/2021/11/09/JavaScript/%E5%AF%B9%E8%B1%A1/JavaScript%E5%8E%9F%E5%9E%8B%E9%93%BE/","path":"2021/11/09/JavaScript/对象/JavaScript原型链/","title":"JavaScript原型链"}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>JavaScript原型链 | tallgy's blog</title>
  




  <noscript>
    <link rel="stylesheet" href="/css/noscript.css">
  </noscript>
</head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <i class="logo-line"></i>
      <h1 class="site-title">tallgy's blog</h1>
      <i class="logo-line"></i>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>







</div>
        
  
  <div class="toggle sidebar-toggle" role="button">
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
  </div>

  <aside class="sidebar">

    <div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
            <div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#JavaScript%E5%8E%9F%E5%9E%8B%E9%93%BE"><span class="nav-number">1.</span> <span class="nav-text">JavaScript原型链</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#JavaScript-%E7%BB%A7%E6%89%BF"><span class="nav-number">2.</span> <span class="nav-text">JavaScript 继承</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#new-%E6%96%B9%E6%B3%95%E7%9A%84%E8%A1%8C%E4%B8%BA"><span class="nav-number">2.1.</span> <span class="nav-text">new 方法的行为</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#JavaScript-%E7%BB%A7%E6%89%BF%EF%BC%9A"><span class="nav-number">2.2.</span> <span class="nav-text">JavaScript 继承：</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%BB%A7%E6%89%BF%E7%9A%84%E6%80%9D%E8%B7%AF"><span class="nav-number">2.2.1.</span> <span class="nav-text">继承的思路</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8E%9F%E5%9E%8B%E5%92%8C%E6%9E%84%E9%80%A0%E5%99%A8"><span class="nav-number">2.2.2.</span> <span class="nav-text">原型和构造器</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#new-%E6%96%B9%E6%B3%95%E5%AE%9E%E7%8E%B0"><span class="nav-number">2.2.3.</span> <span class="nav-text">new 方法实现</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#new-%E5%85%B3%E9%94%AE%E5%AD%97%E4%BC%9A%E8%BF%9B%E8%A1%8C%E5%A6%82%E4%B8%8B%E7%9A%84%E6%93%8D%E4%BD%9C%EF%BC%9A"><span class="nav-number">2.2.3.1.</span> <span class="nav-text">new 关键字会进行如下的操作：</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%BD%93%E4%BB%A3%E7%A0%81-new-Foo-%E6%89%A7%E8%A1%8C%E6%97%B6%EF%BC%8C%E4%BC%9A%E5%8F%91%E7%94%9F%E4%BB%A5%E4%B8%8B%E4%BA%8B%E6%83%85%EF%BC%9A"><span class="nav-number">2.2.3.2.</span> <span class="nav-text">当代码 new Foo(...) 执行时，会发生以下事情：</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%BB%A7%E6%89%BF%E7%9A%84%E6%96%B9%E5%BC%8F"><span class="nav-number">2.2.4.</span> <span class="nav-text">继承的方式</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%8E%9F%E5%9E%8B%E9%93%BE%E7%BB%A7%E6%89%BF"><span class="nav-number">2.2.4.1.</span> <span class="nav-text">原型链继承</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E7%BB%84%E5%90%88%E7%BB%A7%E6%89%BF"><span class="nav-number">2.2.4.2.</span> <span class="nav-text">组合继承</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%AF%84%E7%94%9F%E7%BB%84%E5%90%88%E7%BB%A7%E6%89%BF"><span class="nav-number">2.2.4.3.</span> <span class="nav-text">寄生组合继承</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#%E5%AF%84%E7%94%9F%E7%BB%84%E5%90%88%E7%BB%A7%E6%89%BF%E7%9A%84%E6%80%9D%E8%80%83"><span class="nav-number">2.2.4.3.1.</span> <span class="nav-text">寄生组合继承的思考</span></a></li></ol></li></ol></li></ol></li></ol></li></ol></div>
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author site-overview-item animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">tallgy</p>
  <div class="site-description" itemprop="description">只是一个知识的搬运工</div>
</div>
<div class="site-state-wrap site-overview-item animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/archives/">
          <span class="site-state-item-count">107</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/categories/">
        <span class="site-state-item-count">32</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
          <a href="/tags/">
        <span class="site-state-item-count">74</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>



        </div>
      </div>
    </div>
  </aside>
  <div class="sidebar-dimmer"></div>


    </header>

    
  <div class="back-to-top" role="button" aria-label="返回顶部">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


    <div class="main-inner post posts-expand">


  


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2021/11/09/JavaScript/%E5%AF%B9%E8%B1%A1/JavaScript%E5%8E%9F%E5%9E%8B%E9%93%BE/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          JavaScript原型链
        </h1>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2021-11-09 20:57:32" itemprop="dateCreated datePublished" datetime="2021-11-09T20:57:32+08:00">2021-11-09</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/JavaScript/" itemprop="url" rel="index"><span itemprop="name">JavaScript</span></a>
        </span>
          ，
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/JavaScript/%E9%9A%8F%E7%AC%94/" itemprop="url" rel="index"><span itemprop="name">随笔</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
        <h1 id="JavaScript原型链"><a href="#JavaScript原型链" class="headerlink" title="JavaScript原型链"></a>JavaScript原型链</h1><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">原型链，就像是Java中的继承一样，可以让子类取访问父类的属性，可以将一些公用的东西写在原型上。</span><br><span class="line">是一个 __proto__ 的不断指向上一层。</span><br><span class="line"></span><br><span class="line">同时箭头函数没有 prototype ，所以不能使用new方法</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>先看一张图，简单来说</p>
<p>​        原型其实就是一个方法的实例，然后每一个方法的实例有一个__proto__ 的指向。这个指向会直到指到null为止。这样所生产的就是一个原型链，对于在本层找不到的方法，会通过原型链逐层向上查找。</p>
<p>​        一个方法是和一个原型对应的，而一个原型又是一个另一个方法的实例，所以这里的对应关系在于，一个方法的实例默认是没有constructor构造函数，此时这个实例就是一个单纯的底层实例，但是如果我们将一个构造函数的原型指向了这个实例，并且将这个实例的构造器指向了原型， 那么这个实例就已经算是一个原型了，此时就已经不是一个单纯的底层实例了。</p>
<p>​        顶层的方法就是 Function，顶层的原型就是Object.prototype，而Object方法确实使用了Function的原型。</p>
<img src="/.io//290701352241158.jpg" alt="290701352241158" style="zoom:67%;">



<h1 id="JavaScript-继承"><a href="#JavaScript-继承" class="headerlink" title="JavaScript 继承"></a>JavaScript 继承</h1><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">function Fn() &#123;</span><br><span class="line">  this.name = 1;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">let a = new Fn();</span><br><span class="line"></span><br><span class="line">此时的</span><br><span class="line">a.__proto__ = Fn.prototype</span><br><span class="line">a.__proto__.constructor = Fn;</span><br></pre></td></tr></table></figure>

<h2 id="new-方法的行为"><a href="#new-方法的行为" class="headerlink" title="new 方法的行为"></a>new 方法的行为</h2><p>​        我们要这样思考，这个new方法。</p>
<ul>
<li>new 一个方法，会创建的一个this的指向。</li>
<li>然后会执行这个方法，执行结束之后。</li>
<li>创建一个 __proto__  指向了 方法的 prototype 的指向。</li>
<li>然后就进行返回。</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">let _this = &#123;&#125;;</span><br><span class="line">let result = Fn.apply(_this, args);</span><br><span class="line">_this.__proto__ = Fn.prototype;</span><br><span class="line">return typeof result === &#x27;object&#x27; ? result : __this__;</span><br></pre></td></tr></table></figure>

<p>​        同时这里，在进行 new 方法的调用时，我们知道，如果返回的是一个引用类型，那么便会直接返回这个引用类型，如果返回的是一个值类型，那么返回的便是自己所创建的this指向。我们可以知道一个引用类型，无论你是使用的new方法，还是直接进行的创建的引用类型。其结果都会创建原型。</p>
<p><strong>注意</strong>：</p>
<p>​        对于一个值类型，进行了new 方法，也会变成引用类型的。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">let x = new Number(1);</span><br><span class="line">let y = new Number(1);</span><br><span class="line"></span><br><span class="line">console.log(x === y); //false</span><br></pre></td></tr></table></figure>



<h2 id="JavaScript-继承："><a href="#JavaScript-继承：" class="headerlink" title="JavaScript 继承："></a><strong>JavaScript 继承</strong>：</h2><h3 id="继承的思路"><a href="#继承的思路" class="headerlink" title="继承的思路"></a>继承的思路</h3><p>继承，简单的理解就是，子类的实例可以访问父类的方法</p>
<p>同时我们可以知道，父类的方法，创建的实例才能进行调用。</p>
<p>而父类的prototype，已经可以算作为父类的父类的方法了。</p>
<p>所以，我们在不考虑上级的方法之前，需要将父类的方法进行传递，</p>
<p>这里，可以考虑使用一个新的对象进行指定。如果我一个新对象</p>
<h3 id="原型和构造器"><a href="#原型和构造器" class="headerlink" title="原型和构造器"></a>原型和构造器</h3><p>这里和Java的一个不同点</p>
<p>我印象中，Java是子类有多个，父类越来越少的一种情况，</p>
<img src="/.io//image-20211110100356010.png" alt="image-20211110100356010" style="zoom:67%;">

<p>​        一开始，我是这样思考的，构造函数和实例是对应的，而构造函数的原型应该是属于上层的一个实例了。</p>
<p>​        但是你仔细观察，发现，一个构造函数的原型是和构造函数进行了对应。思想应该是每个实例都有一个原型，但是其原型默认是没有constructor的（这里可以使用 hasOwnProperty 进行证明）。我们所使用的constructor属性其实都是我们的实例的原型  __proto__ 中的constructor，但是实例的原型为什么会带有constructor，这里我的认为是，一个函数默认在词法编译阶段，会默认指向一个prototype，而这个行为就是 </p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Fn.protorype = new Object();</span><br><span class="line">Fn.prototype.constructor = Fn;</span><br></pre></td></tr></table></figure>

<p>​    简单来说，就是在没有指定的情况下，默认先创建一个顶级的对象实例，里面只有最原始的方法，然后再对这个实例创建一个本函数的构造行为。</p>
<img src="/.io//image-20211110101346723.png" alt="image-20211110101346723" style="zoom:67%;">

<p>​        而这个JavaScript是每个子类，都会将父类进行一次实例的操作，所以造成了每个父类的实例和子类的构造函数一一对应了。</p>
<h3 id="new-方法实现"><a href="#new-方法实现" class="headerlink" title="new 方法实现"></a>new 方法实现</h3><h4 id="new-关键字会进行如下的操作："><a href="#new-关键字会进行如下的操作：" class="headerlink" title="new 关键字会进行如下的操作："></a><strong><code>new</code> 关键字会进行如下的操作：</strong></h4><ol>
<li>创建一个空的简单JavaScript对象（即<code>&#123;&#125;</code>）；</li>
<li>为步骤1新创建的对象添加属性**<strong>proto</strong>**，将该属性链接至构造函数的原型对象 ；</li>
<li>将步骤1新创建的对象作为<code>this</code>的上下文 ；</li>
<li>如果该函数没有返回对象，则返回<code>this</code>。</li>
</ol>
<h4 id="当代码-new-Foo-执行时，会发生以下事情："><a href="#当代码-new-Foo-执行时，会发生以下事情：" class="headerlink" title="当代码 new Foo(...) 执行时，会发生以下事情："></a><strong>当代码 <code>new Foo(...)</code> 执行时，会发生以下事情：</strong></h4><ol>
<li>一个继承自 <code>Foo.prototype</code> 的新对象被创建。</li>
<li>使用指定的参数调用构造函数 <em><code>Foo</code><em>，并将 <code>this</code> 绑定到新创建的对象。<code>new Foo</code> 等同于 <em><code>new Foo</code></em><code>()</code>，也就是没有指定参数列表，</em><code>Foo</code></em> 不带任何参数调用的情况。</li>
<li>由构造函数返回的对象就是 <code>new</code> 表达式的结果。如果构造函数没有显式返回一个对象，则使用步骤1创建的对象。（一般情况下，构造函数不返回值，但是用户可以选择主动返回对象，来覆盖正常的对象创建步骤）</li>
</ol>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">function create(Fn, ...args) &#123;</span><br><span class="line">  let _this = &#123;&#125;;</span><br><span class="line">  let result = Fn.apply(_this, args);</span><br><span class="line">  _this.__proto__ = Fn.prototype;</span><br><span class="line">  return typeof result === &#x27;object&#x27; ? result : _this;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="继承的方式"><a href="#继承的方式" class="headerlink" title="继承的方式"></a>继承的方式</h3><h4 id="原型链继承"><a href="#原型链继承" class="headerlink" title="原型链继承"></a>原型链继承</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Children.prototype = new Father();</span><br><span class="line">Children.prototype.constructor = Children;</span><br></pre></td></tr></table></figure>

<p>​        很简单的理解，就是直接将子类的原型修改为了父类的实例，然后再对实例的constructor进行一个校准，修改为子类的构造。</p>
<p>​        执行new方法的行为的步骤：</p>
<ul>
<li>产生一个this指向，__proto__  的添加，指向为children.prototype。就是 Father的实例。</li>
<li>执行children的构造函数，this指向的调用。</li>
<li>返回。</li>
</ul>
<p><strong>缺点</strong>：</p>
<ul>
<li>对于要在原型上添加修改的方法，需要在 new Father 之后，因为这个是直接将一个地址进行了转换。</li>
<li>其次就是不会将参数传递到父类。只适合不带参数的。</li>
<li>因为实例是在直接对原型的创建，所以，所有的实例都是共有的。当然，因为这个创建本就无法带参数，共有实例其实并没有什么问题。</li>
</ul>
<h4 id="组合继承"><a href="#组合继承" class="headerlink" title="组合继承"></a>组合继承</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">function Children() &#123;</span><br><span class="line">	Father.call(this);</span><br><span class="line">&#125;</span><br><span class="line">Children.prototype = new Father();</span><br><span class="line">Children.prototype.constructor = Children;</span><br></pre></td></tr></table></figure>

<p>​        这个和原型链继承大同小异，就是多了一个在构造函数内部使用call方法调用父类。使用call方法调用时是不会产生 __proto__  和 constructor 的。但是你可能会发现自己测试还是有啊，但是你仔细观察，其实你自己测试所生成的 __proto__  和 constructor 是在创建对象的时候生成的。所以，其实并没有真正的生成。</p>
<p><strong>缺点</strong>：</p>
<ul>
<li>new 方法 和 call 方法都生成了一份实例。</li>
</ul>
<h4 id="寄生组合继承"><a href="#寄生组合继承" class="headerlink" title="寄生组合继承"></a>寄生组合继承</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">function Children() &#123;</span><br><span class="line">	Father.call(this);</span><br><span class="line">&#125;</span><br><span class="line">(function () &#123;</span><br><span class="line">	let Super = function() &#123;&#125;;</span><br><span class="line">	Super.prototype = Father.prototype;</span><br><span class="line">	Children.prototype = new Super();</span><br><span class="line">	Children.prototype.constructor = Children;</span><br><span class="line">&#125;)();</span><br></pre></td></tr></table></figure>

<p>​        我们可以查看这个和 组合继承的区别，使用了一个空方法将Father的原型复制了过来，所以new所生成的方法就只生成了一个空对象，和一个原型。Father的方法实则已经在call方法里面进行了调用。</p>
<h5 id="寄生组合继承的思考"><a href="#寄生组合继承的思考" class="headerlink" title="寄生组合继承的思考"></a>寄生组合继承的思考</h5><p>为什么我们会这样使用寄生组合继承</p>
<p>我们可以从各个方面进行思考，</p>
<p>首先继承无非就是子类想要使用上父类的元素，然后这里就需要调用父类的方法</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">function Children() &#123;</span><br><span class="line">	</span><br><span class="line">&#125;</span><br><span class="line">Children.prototype = new Father();</span><br><span class="line"></span><br><span class="line">这个方法的问题是无法传参。</span><br><span class="line">这里修改了原型指向，所以需要进行构造函数的指向转变</span><br><span class="line">Children.prototype.constructor = Children;</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">function Children() &#123;</span><br><span class="line">	let instance = new Father(xxx);</span><br><span class="line">	</span><br><span class="line">	return instance;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">这个方法是可以传递参数了，但是这个方法就不是父类的实例了，因为是在子类被创建，所以我们要不就是对子类也同用这个instance对象进行操作。但是这样有点不符合一种规范</span><br><span class="line">这里是使用了instance方式，而instance实则是父类的实例，所以如果需要进行子类实例的操作。需要在new Fahter的后面，然后将this转换成instance，然后对于proto和构造 函数都是父函数的。很有问题的感觉</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">function Children() &#123;</span><br><span class="line">	Father.call(this);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">在这里，我是将父元素的方法进行了执行，当然，如果是对于父元素返回的是一个对象的，那么将会是一个不同的操作，但是在正常的情况下，通过这个可以获取到父元素的构造函数执行方法，但是，问题在于没有原型指向的改变。所以我们需要进行原型指向的改变。</span><br><span class="line">简单来说，这里已经获取到了父函数的实例对象，只需要将原型指向进行改变即可</span><br><span class="line">Children.prototype = new Father();</span><br><span class="line">Children.prototype.constructor = Children;</span><br><span class="line">通过上面这个方法，我们获取到了原型的指向，修改为了父元素的实例。唯一的问题就是进行了两次Father的使用，可以考虑对于父函数的实例进行一个处理</span><br><span class="line"></span><br><span class="line">let Super = funtion() &#123;&#125;;</span><br><span class="line">Super.prototype = Father.prototype;</span><br><span class="line">Children.prototype = new Super();</span><br><span class="line">Children.prototype.constructor = Children;</span><br><span class="line">区别，new的是Super，Super里面没有实例，所以里面只有一个原型的指向。</span><br><span class="line">而Super的原型的指向已经被修改为了Father的原型。</span><br><span class="line">此时我们只需要在对构造函数进行一个修改即可。</span><br></pre></td></tr></table></figure>



<p>所以最后我们使用了寄生组合继承，方式就是在内部使用call方法调用了父函数，获取了父函数的实例方法，然后在外部创建一个空函数，原型指向了父函数的原型，然后再对其实例赋值给了子类的原型，此时因为空函数的实例内部是没有的，所以其实内部的共有属性就只有proto，和 constructor。然后在修改原型的构造。</p>
<p>​        所以整的来说，这个方式，只生成了相同的父类的实例的方法，并且放在了子类的实例中，所以不会出现共有属性，其次就是原型是在外部进行的实现，所以原型又是共有的。其次就是对原型的构造函数进行了指向。</p>
<p>​        所以很完美。</p>

    </div>

    
    
    

    <footer class="post-footer">
          <div class="post-tags">
              <a href="/tags/%E9%9A%8F%E7%AC%94/" rel="tag"># 随笔</a>
              <a href="/tags/JavaScript/" rel="tag"># JavaScript</a>
              <a href="/tags/%E5%8E%9F%E5%9E%8B%E9%93%BE/" rel="tag"># 原型链</a>
          </div>

        

          <div class="post-nav">
            <div class="post-nav-item">
                <a href="/2021/11/07/Node%20JS/JavaScript%E4%BA%8B%E4%BB%B6%E5%BE%AA%E7%8E%AF/" rel="prev" title="JavaScript事件循环">
                  <i class="fa fa-chevron-left"></i> JavaScript事件循环
                </a>
            </div>
            <div class="post-nav-item">
                <a href="/2021/11/10/JavaScript/ES6/JavaScript%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0/" rel="next" title="JavaScript箭头函数">
                  JavaScript箭头函数 <i class="fa fa-chevron-right"></i>
                </a>
            </div>
          </div>
    </footer>
  </article>
</div>






</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">


<div class="copyright">
  &copy; 
  <span itemprop="copyrightYear">2023</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">tallgy</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.js.org/muse/" rel="noopener" target="_blank">NexT.Muse</a> 强力驱动
  </div>

    </div>
  </footer>

  
  <script src="https://cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/schemes/muse.js"></script><script src="/js/next-boot.js"></script>

  





  





</body>
</html>
